<?php
class CmsPageModel extends ModelTree
{
    protected $resourceId = 'AdminResource';
    protected static $instance;

    public static function GetInstance()
    {
        return self::$instance ? self::$instance : self::$instance = new CmsPageModel();
    }

    protected function LoadFields()
    {
        parent::LoadFields();
        $this->SetForeignKey('parent_id', $this->GetTableName(), 'id');
        $this->SetForeignKey('resource_id', AclResourceModel::GetInstance()->GetTableName(), 'id');
        $this->SetForeignKey('layout', CmsLayoutModel::GetInstance()->GetTableName(), 'id');
        $this->SetForeignKey('template', CmsTemplateModel::GetInstance()->GetTableName(), 'id');

        $this->AddOneToManyRelation('cms_page', 'parent_id');
        $this->AddOneToManyRelation('cms_block', 'page_id');
    }

    public function GetBlocks($pageId, $position = null)
    {
        $cond = new SqlCondition();
        $cond->AddString('page_id', $pageId);
        $cond->AddNumber('enabled', 1);
        return CmsBlockModel::GetInstance()->Find($cond, null, 'sort_order');
    }

    public function GetLayoutById($id)
    {
        return $this->FindScalarById($id, 'layout');
    }

    public function Insert($item)
    {
        $this->ValidateName($item);
        $this->FormatPath($item);
        $id = parent::Insert($item);
        $this->GetCache($id)->Clear();
        return $id;
    }

    protected function FormatPath(&$item)
    {
        $parent_id = array_get($item, 'parent_id');
        $item['path'] = $this->GeneratePath($parent_id, $item['name']);
    }

    protected function GeneratePath($parent_id, $name)
    {
        $parent_path = $parent_id ? $this->FindScalarById($parent_id, 'path') : null;
        $parent_path = String::RemoveTrailingSlash($parent_path);
        $name = String::CropBegin(FS, $name);
        return $parent_path ? $parent_path.FS.$name : $name;
    }

    protected function ValidateName(&$item)
    {
        $name = trim($item['name']);
        if (!$name) throw new Exception('name is required');
        $item['name'] = $name;
    }

    public function Update($item)
    {
        if (isset($item['name'])) $this->ValidateName($item);
        $this->UpdatePath($item);
        $out = parent::Update($item);
        if (isset($item['path'])) $this->UpdateChilds($item['id']);
        $this->GetCache($item['id'])->Clear();
        return $out;
    }

    protected function UpdatePath(&$item)
    {
        if (isset($item['name']) && isset($item['parent_id']))
        {
            $name = $item['name'];
            $parent_id = $item['parent_id'];
            $item['path'] = $this->GeneratePath($parent_id, $name);
        }
        else if (isset($item['name']))
        {
            $name = $item['name'];
            $parent_id = $this->FindScalarById($item['id'], 'parent_id');
            $item['path'] = $this->GeneratePath($parent_id, $name);
        }
        else if (isset($item['parent_id']))
        {
            $name = $this->FindScalarById($item['id'], 'name');
            $parent_id = $item['parent_id'];
            $item['path'] = $this->GeneratePath($parent_id, $name);
        }
    }

    protected function UpdateChilds($parent_id)
    {
        $childs = $this->GetChilds($parent_id, 'id, name');
        foreach ($childs as $child)
        {
            $item['id'] = $child['id'];
            $item['path'] = $this->GeneratePath($parent_id, $child['name']);
            $this->Update($item);
        }
    }

    public static function GetEnabledPageByPath($path)
    {
        $cache = new CacheData('CmsPageModel', $path);
        if ($cache->IsValid())
            return $cache->Render();
        else
        {
            $cond = new SqlCondition();
            $cond->AddString('path', $path);
            $cond->AddNumber('enabled', 1);
            $page = self::GetInstance()->FindOne($cond);
            $cache->Save($page);
            return $page;
        }
    }

    public function Del($id)
    {
        $this->GetCache($id)->Clear();
        return parent::Del($id);
    }

    public function GetCache($id)
    {
        $path = $this->FindScalarById($id, 'path');
        return new CacheData($this->GetClassName(), $path);
    }
}
?>
